﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YougeBookmark.Data;
using YougeBookmark.Models;
using YougeBookmark.Utilities;

namespace YougeBookmark.Services
{
    public class BookmarkManager
    {
        private readonly BookmarkRepository _bookmarkRepo;
        private readonly TagRepository _tagRepo;
        private readonly HtmlParser _htmlParser;
        private readonly ImageHelper _imageHelper;
        private readonly Logger _logger;
        private readonly BookmarkTagRepository _bookmarkTagRepo;
        public BookmarkManager(
            BookmarkRepository bookmarkRepo,
            TagRepository tagRepo,
            HtmlParser htmlParser,
            ImageHelper imageHelper,
            Logger logger,
            BookmarkTagRepository bookmarkRepository)
        {
            _bookmarkRepo = bookmarkRepo ?? throw new ArgumentNullException(nameof(bookmarkRepo));
            _tagRepo = tagRepo ?? throw new ArgumentNullException(nameof(tagRepo));
            _htmlParser = htmlParser ?? throw new ArgumentNullException(nameof(htmlParser));
            _imageHelper = imageHelper ?? throw new ArgumentNullException(nameof(imageHelper));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _bookmarkTagRepo = bookmarkRepository ?? throw new ArgumentNullException(nameof(bookmarkRepository));
        }

        public async Task<ParsedHtmlData> ParseUrlAsync(string url)
        {
            try
            {
                return await _htmlParser.Parse(url);
            }
            catch (Exception ex)
            {
                _logger.Error($"URL解析失败: {url} - {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 创建完整书签流程（解析网页+保存数据）
        /// </summary>
        public async Task<Bookmark> CreateBookmarkAsync(string url, List<string> tagNames, string remark = null)
        {
            try
            {
                // 避免重复创建
                var existing = await _bookmarkRepo.GetByUrlAsync(url);
                if (existing != null)
                {
                    _logger.Warn($"书签已存在: {url}");
                    return existing;
                }

                // 解析网页元数据
                var parsedData = await _htmlParser.Parse(url);
                if (parsedData == null) throw new InvalidOperationException("网页解析失败");

                // 处理缩略图
                string thumbnailPath = null;
                if (parsedData.ImageData != null)
                {
                    thumbnailPath = _imageHelper.SaveImage(
                        parsedData.ImageData,
                        maxWidth: 800
                    );
                }

                // 创建书签实体
                var bookmark = new Bookmark
                {
                    Url = url,
                    Title = parsedData.Title?.Trim() ?? "无标题",
                    Summary = parsedData.Summary?.Trim() ?? "",
                    ThumbnailPath = thumbnailPath ?? "",
                    Remark = remark?.Trim() ?? "",
                };

                // 处理标签关联
                var tags = await ProcessTagsAsync(tagNames);
                using var transaction = _bookmarkRepo.BeginTransaction();
                try
                {
                    // 保存书签
                    var created = await _bookmarkRepo.AddAsync(bookmark);
                    if (created == null) return null;

                    // 关联标签
                    foreach (var tag in tags)
                    {
                        //await _tagRepo.CreateAssociationAsync(created.Id, tag.Id);
                        await _bookmarkTagRepo.CreateAssociationAsync(created.Id, tag.Id);
                    }

                    transaction.Commit();
                    return created;
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"书签创建失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 更新书签可编辑字段及标签
        /// </summary>
        public async Task<Bookmark> UpdateBookmarkAsync(int bookmarkId, string title, string summary,
            string remark, byte[] newImage = null, List<string> newTags = null)
        {
            try
            {
                var bookmark = await _bookmarkRepo.GetFullByIdAsync(bookmarkId);
                if (bookmark == null) return null;

                // 更新基础字段 
                bookmark.Title = title?.Trim();
                bookmark.Summary = summary?.Trim();
                bookmark.Remark = remark?.Trim();

                // 处理图片替换
                if (newImage != null)
                {
                    bookmark.ThumbnailPath = _imageHelper.ReplaceImage(
                        bookmark.ThumbnailPath,
                        newImage
                    );
                }

                // 处理标签更新
                if (newTags != null)
                {
                    await UpdateBookmarkTagsAsync(bookmark, newTags);
                }

                return await _bookmarkRepo.UpdateAsync(bookmark);
            }
            catch (Exception ex)
            {
                _logger.Error($"书签更新失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 分页查询书签（支持多标签筛选）
        /// </summary>
        public async Task<(List<Bookmark> Items, int Total)> SearchBookmarksAsync(
            string keyword = null,
            List<string> tags = null,
            DateTime? startDate = null,
            DateTime? endDate = null,
            int page = 1,
            int pageSize = 20)
        {
            try
            {
                // 转换标签名称到ID
                List<int> tagIds = null;
                if (tags?.Count > 0)
                {
                    var existingTags = await _tagRepo.GetByNamesAsync(tags);
                    tagIds = existingTags.Select(t => t.Id).ToList();
                }

                return await _bookmarkRepo.SearchAsync(
                    keyword: keyword,
                    tagIds: tagIds,
                    startDate: startDate,
                    endDate: endDate,
                    pageIndex: page - 1,
                    pageSize: pageSize
                );
            }
            catch (Exception ex)
            {
                _logger.Error($"书签查询失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 处理标签名称集合（合并现有标签和新建标签）
        /// </summary>
        private async Task<List<Tag>> ProcessTagsAsync(IEnumerable<string> tagNames)
        {
            var uniqueNames = tagNames?
                .Where(n => !string.IsNullOrWhiteSpace(n))
                .Select(n => n.Trim())
                .Distinct()
                .ToList() ?? new List<string>();

            var result = new List<Tag>();
            foreach (var name in uniqueNames)
            {
                var tag = await _tagRepo.GetByNameAsync(name) ?? await _tagRepo.CreateAsync(name);
                if (tag != null) result.Add(tag);
            }
            return result;
        }

        /// <summary>
        /// 同步书签标签关系（增量更新）
        /// </summary>
        private async Task UpdateBookmarkTagsAsync(Bookmark bookmark, List<string> newTagNames)
        {
            var existingTags = bookmark.Tags.Select(t => t.Name).ToList();
            var tagsToAdd = newTagNames.Except(existingTags).ToList();
            var tagsToRemove = existingTags.Except(newTagNames).ToList();

            // 添加新关联
            foreach (var tagName in tagsToAdd)
            {
                var tag = await _tagRepo.GetByNameAsync(tagName) ?? await _tagRepo.CreateAsync(tagName);
                if (tag != null)
                {
                    //await _tagRepo.CreateAssociationAsync(bookmark.Id, tag.Id);
                    await _bookmarkTagRepo.CreateAssociationAsync(bookmark.Id, tag.Id);
                }
            }

            // 移除旧关联
            foreach (var tagName in tagsToRemove)
            {
                var tag = await _tagRepo.GetByNameAsync(tagName);
                if (tag != null)
                {
                    await _tagRepo.DeleteAssociationAsync(bookmark.Id, tag.Id);
                }
            }
        }
    }
}